package com.jsu.clubmanagementsystem.service.review.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jsu.clubmanagementsystem.common.ErrorCode;
import com.jsu.clubmanagementsystem.constant.UserConstant;
import com.jsu.clubmanagementsystem.exception.BusinessException;
import com.jsu.clubmanagementsystem.model.dto.review.ReviewConsequence;
import com.jsu.clubmanagementsystem.model.dto.review.ReviewQueryRequest;
import com.jsu.clubmanagementsystem.model.entity.*;
import com.jsu.clubmanagementsystem.model.enums.ApplicationTypeEnum;
import com.jsu.clubmanagementsystem.model.enums.ReviewResultEnum;
import com.jsu.clubmanagementsystem.model.vo.review.BatchReviewConsequence;
import com.jsu.clubmanagementsystem.model.vo.review.ErrorReviewVO;
import com.jsu.clubmanagementsystem.model.vo.review.ReviewVO;
import com.jsu.clubmanagementsystem.model.vo.user.UserVO;
import com.jsu.clubmanagementsystem.mapper.ReviewMapper;
import com.jsu.clubmanagementsystem.service.activity.ActivityService;
import com.jsu.clubmanagementsystem.service.application.ActivityApplicationService;
import com.jsu.clubmanagementsystem.service.application.ClubApplicationService;
import com.jsu.clubmanagementsystem.service.application.UserApplicationService;
import com.jsu.clubmanagementsystem.service.club.ClubService;
import com.jsu.clubmanagementsystem.service.review.ReviewService;
import com.jsu.clubmanagementsystem.service.user.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 24753
* @description 针对表【review(审核)】的数据库操作Service实现
* @createDate 2025-05-17 17:05:46
*/
@Service
public class ReviewServiceImpl extends ServiceImpl<ReviewMapper, Review>
    implements ReviewService {

    @Resource
    private UserService userService;

    @Resource
    private ClubService clubService;

    @Resource
    private ActivityService activityService;

    @Resource
    private UserApplicationService userApplicationService;

    @Resource
    private ClubApplicationService clubApplicationService;

    @Resource
    private ActivityApplicationService activityApplicationService;

    @Resource
    private AcceptedReviewProcessor acceptedReviewProcessor;

    /**
     * 通过申请 分流
     *
     * @param reviewConsequence
     * @return
     */
    @Override
    @Transactional
    public Long acceptReview(ReviewConsequence reviewConsequence) {
        // 验证参数（存在性、安全逻辑和参数检验）
        Review review = new Review();
        review.setUserId(reviewConsequence.getUserId());
        review.setType(reviewConsequence.getType());
        review.setApplicationId(reviewConsequence.getApplicationId());
        review.setContent(reviewConsequence.getContent());
        review.setResult(reviewConsequence.getResult());
        this.reviewValidation(review);

        // 根据申请类型分发到不同的处理方法
        UserApplication userApplication = null;
        ClubApplication clubApplication = null;
        ActivityApplication activityApplication = null;
        Long applicationId = review.getApplicationId();
        Integer type = review.getType();
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);

        switch (applicationType) {
            case ApplicationTypeEnum.DELETE_USER:
                userApplication = userApplicationService.getById(applicationId);
                acceptedReviewProcessor.doDeleteUserApplicationReview(userApplication);
                break;

            case ApplicationTypeEnum.JOIN_CLUB:
                userApplication = userApplicationService.getById(applicationId);
                acceptedReviewProcessor.doJoinClubApplicationReview(userApplication);
                break;

            case ApplicationTypeEnum.QUIT_CLUB:
                userApplication = userApplicationService.getById(applicationId);
                acceptedReviewProcessor.doQuitClubApplicationReview(userApplication);
                break;

            case ApplicationTypeEnum.ENGAGE_ACTIVITY:
                userApplication = userApplicationService.getById(applicationId);
                acceptedReviewProcessor.doEngageActivityApplicationReview(userApplication);
                break;

            case ApplicationTypeEnum.QUIT_ACTIVITY:
                userApplication = userApplicationService.getById(applicationId);
                acceptedReviewProcessor.doQuitActivityApplicationReview(userApplication);
                break;

            case ApplicationTypeEnum.CREATE_CLUB:
                clubApplication = clubApplicationService.getById(applicationId);
                acceptedReviewProcessor.doCreateClubApplicationReview(clubApplication);
                break;

            case ApplicationTypeEnum.DELETE_CLUB:
                clubApplication = clubApplicationService.getById(applicationId);
                acceptedReviewProcessor.doDeleteClubApplicationReview(clubApplication);
                break;

            case ApplicationTypeEnum.CHANGE_CLUB_INFO:
                clubApplication = clubApplicationService.getById(applicationId);
                acceptedReviewProcessor.doUpdateClubApplicationReview(clubApplication);
                break;

            case ApplicationTypeEnum.CREATE_ACTIVITY:
                activityApplication = activityApplicationService.getById(applicationId);
                acceptedReviewProcessor.doCreateActivityApplicationReview(activityApplication);
                break;

            case ApplicationTypeEnum.DELETE_ACTIVITY:
                activityApplication = activityApplicationService.getById(applicationId);
                acceptedReviewProcessor.doDeleteActivityApplicationReview(activityApplication);
                break;

            case ApplicationTypeEnum.CHANGE_ACTIVITY_INFO:
                activityApplication = activityApplicationService.getById(applicationId);
                acceptedReviewProcessor.doUpdateActivityApplicationReview(activityApplication);
                break;

            default:
                throw new BusinessException(ErrorCode.PARAM_ERROR, "不支持的申请类型");
        }

        //修改申请审核状态
        if (userApplication != null) {
            userApplication.setResult(ReviewResultEnum.ACCEPT.getCode());
            if (!userApplicationService.updateById(userApplication)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "修改申请审核状态失败");
            }
        } else if (clubApplication != null) {
            clubApplication.setResult(ReviewResultEnum.ACCEPT.getCode());
            if (!clubApplicationService.updateById(clubApplication)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "修改申请审核状态失败");
            }
        } else if (activityApplication != null) {
            activityApplication.setResult(ReviewResultEnum.ACCEPT.getCode());
            if (!activityApplicationService.updateById(activityApplication)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "修改申请审核状态失败");
            }
        }

        //插入审核数据
        if (!this.save(review)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "插入审核数据失败");
        }
        return review.getId();
    }

    /**
     * 拒绝申请
     *
     * @param reviewConsequence
     * @return
     */
    @Override
    @Transactional
    public Long rejectReview(ReviewConsequence reviewConsequence) {
        // 验证参数（存在性、安全逻辑和参数检验）
        Review review = new Review();
        review.setUserId(reviewConsequence.getUserId());
        review.setType(reviewConsequence.getType());
        review.setApplicationId(reviewConsequence.getApplicationId());
        review.setContent(reviewConsequence.getContent());
        review.setResult(reviewConsequence.getResult());
        this.reviewValidation(review);

        //根据不同的申请类型处理
        Integer type = reviewConsequence.getType();
        Long applicationId = reviewConsequence.getApplicationId();
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);

        if (applicationType == ApplicationTypeEnum.DELETE_USER ||
                applicationType == ApplicationTypeEnum.JOIN_CLUB ||
                applicationType == ApplicationTypeEnum.QUIT_CLUB ||
                applicationType == ApplicationTypeEnum.ENGAGE_ACTIVITY ||
                applicationType == ApplicationTypeEnum.QUIT_ACTIVITY) {
            UserApplication application = new UserApplication();
            application.setId(applicationId);
            application.setResult(ReviewResultEnum.REJECT.getCode());
            if (!userApplicationService.updateById(application)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "修改申请审核状态失败");
            }
        } else if (applicationType == ApplicationTypeEnum.CREATE_CLUB ||
                applicationType == ApplicationTypeEnum.DELETE_CLUB ||
                applicationType == ApplicationTypeEnum.CHANGE_CLUB_INFO) {
            ClubApplication application = new ClubApplication();
            application.setId(applicationId);
            application.setResult(ReviewResultEnum.REJECT.getCode());
            if (!clubApplicationService.updateById(application)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "修改申请审核状态失败");
            }
        } else if (applicationType == ApplicationTypeEnum.CREATE_ACTIVITY ||
                applicationType == ApplicationTypeEnum.DELETE_ACTIVITY ||
                applicationType == ApplicationTypeEnum.CHANGE_ACTIVITY_INFO) {
            ActivityApplication application = new ActivityApplication();
            application.setId(applicationId);
            application.setResult(ReviewResultEnum.REJECT.getCode());
            if (!activityApplicationService.updateById(application)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "修改申请审核状态失败");
            }
        }

        //修改审核状态
        if (!this.save(review)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "插入审核数据失败");
        }
        return review.getId();
    }

    /**
     * 批量处理审核
     *
     * @param reviewConsequences
     * @return
     */
    @Override
    public BatchReviewConsequence processBatchReview(List<ReviewConsequence> reviewConsequences) {
        BatchReviewConsequence batchReviewConsequence = new BatchReviewConsequence();
        int sum = reviewConsequences.size();
        batchReviewConsequence.setSum(sum);

        List<ErrorReviewVO> errorReviewList = new ArrayList<>();
        for (int i = 0; i < sum; i++) {
            Long reviewId = 0L;
            ReviewConsequence consequence = reviewConsequences.get(i);
            if (consequence.getResult().equals(ReviewResultEnum.ACCEPT.getCode())) {
                reviewId = this.acceptReview(consequence);
            } else if (consequence.getResult().equals(ReviewResultEnum.REJECT.getCode())) {
                reviewId = this.rejectReview(consequence);
            }

            if (reviewId == 0L) {
                ErrorReviewVO errorReviewVO = ErrorReviewVO.objToVo(consequence.getApplicationId(), consequence.getType());
                errorReviewList.add(errorReviewVO);
            }
        }

        int reviewedSum = sum - errorReviewList.size();
        batchReviewConsequence.setErrorReviewList(errorReviewList);
        batchReviewConsequence.setReviewedSum(reviewedSum);
        return batchReviewConsequence;
    }

    /**
     * 获取审核封装
     *
     * @param review
     * @return
     */
    public ReviewVO getReviewVo(Review review) {
        if (review == null)
            return null;
        ReviewVO reviewVO = ReviewVO.objToVo(review);
        ReviewResultEnum reviewResult = ReviewResultEnum.getByCode(review.getResult());
        reviewVO.setResult(reviewResult.getInfo());

        User user = userService.getById(review.getUserId());
        UserVO userVO = UserVO.objToVoLessInfo(user);
        reviewVO.setUserVO(userVO);
        return reviewVO;
    }

    /**
     * 获取申请的审核结果
     *
     * @param applicationId
     * @param applicationType
     * @return
     */
    public Review getReviewByApplication(Long applicationId, Integer applicationType) {
        QueryWrapper<Review> queryWrapper = this.getQueryWrapper(applicationId, applicationType);
        Review review = this.getOne(queryWrapper);
        return review;
    }

    /**
     * 获取申请的审核封装结果
     * @param applicationId
     * @param applicationType
     * @return
     */
    public ReviewVO getReviewVoByApplication(Long applicationId, Integer applicationType){
        Review review = getReviewByApplication(applicationId, applicationType);
        return getReviewVo(review);
    }

    /**
     * 获取审核列表
     *
     * @param queryRequest
     * @return
     */
    public Page<ReviewVO> listReviewVoByPage(ReviewQueryRequest queryRequest) {
        Long id = queryRequest.getId();
        Long userId = queryRequest.getUserId();
        Integer type = queryRequest.getType();
        Long applicationId = queryRequest.getApplicationId();
        Integer result = queryRequest.getResult();

        QueryWrapper<Review> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(type), "type", type);
        queryWrapper.eq(ObjectUtils.isNotEmpty(applicationId), "applicationId", applicationId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(result), "result", result);

        int current = queryRequest.getCurrent();
        int pageSize = queryRequest.getPageSize();
        List<ReviewVO> reviewVoList = this.list(queryWrapper).stream()
                .map(review -> {return this.getReviewVo(review); })
                .collect(Collectors.toList());
        Page<ReviewVO> voPage = new Page<>(current, pageSize);
        voPage.setRecords(reviewVoList);
        return voPage;
    }

    /**
     * 审核数据是否存在
     *
     * @param reviewId
     * @return
     */
    public boolean isExist(Long reviewId) {
        if (reviewId == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "参数为空");
        }
        Review review = this.getById(reviewId);
        return review != null;
    }

    /**
     * 获取查询封装
     * @param applicationId
     * @param applicationType
     * @return
     */
    public QueryWrapper<Review> getQueryWrapper(Long applicationId, Integer applicationType) {
        QueryWrapper<Review> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotEmpty(applicationId), "applicationId", applicationId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(applicationType), "type", applicationType);
        return queryWrapper;
    }

    /**
     * 校验审核结果
     *
     * @param review
     */
    public void reviewValidation(Review review) {
        Long applicationId = review.getApplicationId();
        String content = review.getContent();
        Integer result = review.getResult();
        if (applicationId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少参数");
        }
        if (result.equals(ReviewResultEnum.WAITING.getCode())) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "审核状态错误");
        }
        if (StringUtils.isNotBlank(content) && content.length() > 4096) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "审核意见过长");
        }

        Integer type = review.getType();
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);
        if (applicationType == ApplicationTypeEnum.DELETE_USER ||
                applicationType == ApplicationTypeEnum.JOIN_CLUB ||
                applicationType == ApplicationTypeEnum.QUIT_CLUB ||
                applicationType == ApplicationTypeEnum.ENGAGE_ACTIVITY ||
                applicationType == ApplicationTypeEnum.QUIT_ACTIVITY) {
            if (!userApplicationService.isExist(applicationId)) {
                throw new BusinessException(ErrorCode.NOT_FOUND, "申请不存在");
            }
        } else if (applicationType == ApplicationTypeEnum.CREATE_CLUB ||
                applicationType == ApplicationTypeEnum.DELETE_CLUB ||
                applicationType == ApplicationTypeEnum.CHANGE_CLUB_INFO) {
            if (!clubApplicationService.isExist(applicationId)) {
                throw new BusinessException(ErrorCode.NOT_FOUND, "申请不存在");
            }
        } else if (applicationType == ApplicationTypeEnum.CREATE_ACTIVITY ||
                applicationType == ApplicationTypeEnum.DELETE_ACTIVITY ||
                applicationType == ApplicationTypeEnum.CHANGE_ACTIVITY_INFO) {
            if (!activityApplicationService.isExist(applicationId)) {
                throw new BusinessException(ErrorCode.NOT_FOUND, "申请不存在");
            }
        }
    }

    /**
     * 审核人身份校验
     *
     * @param consequence
     * @param request
     */
    @Override
    public void reviewerValidation(ReviewConsequence consequence, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (!loginUser.getId().equals(consequence.getUserId())) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "当前用户并非审核信息中的审核者");
        }

        //根据审核的申请类型、申请信息验证审核人身份
        Long reviewerId = consequence.getUserId();
        User reviewer = userService.getById(reviewerId);
        if (reviewer == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "审核人不存在");
        }

        Long applicationId = consequence.getApplicationId();
        Integer type = consequence.getType();
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);
        if (applicationType == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "未知的申请类型");
        }

        // 社长审核的：加入社团、退出社团、加入活动、退出活动
        // 管理员审核的：账号注销、创建社团、注销社团、修改社团信息、举办活动、取消活动、修改活动信息
        if (applicationType.equals(ApplicationTypeEnum.JOIN_CLUB) || applicationType.equals(ApplicationTypeEnum.QUIT_CLUB)) {
            UserApplication application = userApplicationService.getById(applicationId);
            if (application == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND, "申请不存在");
            }
            Long clubId = application.getAdditionalInfo();
            if (!clubService.isManagerOfClub(reviewerId, clubId)) {
                throw new BusinessException(ErrorCode.NO_AUTH, "只有目标社团的社长可审核该申请");
            }
        } else if (applicationType.equals(ApplicationTypeEnum.ENGAGE_ACTIVITY) || applicationType.equals(ApplicationTypeEnum.QUIT_ACTIVITY)) {
            UserApplication application = userApplicationService.getById(applicationId);
            if (application == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND, "申请不存在");
            }
            Long activityId = application.getAdditionalInfo();
            Activity activity = activityService.getById(activityId);
            if (activity == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND, "申请的目标活动不存在");
            }
            if (!clubService.isManagerOfClub(reviewerId, activity.getClubId())) {
                throw new BusinessException(ErrorCode.NO_AUTH, "只有目标活动所属社团的社长可审核该申请");
            }
        } else {
            if (!reviewer.getUserRole().equals(UserConstant.USER_ROLE_ADMIN)) {
                throw new BusinessException(ErrorCode.NO_AUTH, "只有系统管理员可审核该申请");
            }
        }
    }
}
